import _ from 'lodash'
import axios from 'axios'
import { Notice } from 'iview'

export const config = {
  headers: {}
}

const _requester = axios.create({
  baseURL: 'http://data.1hole.cn/api',
  timeout: 10000,
  headers: {
    'Api-Version': 1
  }
})

const methods = ['get', 'delete', 'patch', 'post', 'put']

export const requester = new Proxy(_requester, {
  get (obj, prop) {
    if (methods.includes(prop)) {
      return wrapMethod(obj, prop)
    }
    return obj[prop]
  }
})

function wrapMethod (requester, method) {
  return async function (...args) {
    let opts = _.last(args)
    if (_.isObject(opts)) {
      if (!opts.headers) opts.headers = {}
      Object.assign(opts.headers, config.headers)
    } else {
      args.push({ headers: config.headers })
    }

    try {
      let response = await requester[method](...args)
      return [processResult(response.data)]
    } catch (err) {
      return [null, processError(err, method, args)]
    }
  }
}

/** @desc 通用结果处理 */
function processResult (result) {
  // 如果要对meta中的api_key_will_expired_at做处理的话, 就在这里解决
  return result
}

/** @desc 通用错误处理 */
function processError (error, method, args) {
  let _error = error.response && typeof error.response.data !== 'string' ? error.response.data : error

  if (_error.error_code === 1001) {
    // 授权错误, 在这里删除旧token, 重新登陆等
  }

  if (_error.error_message) {
    Notice.error({ title: _error.error_message })
  } else if (error.message.startsWith('Request failed with status code')) {
    Notice.error({ title: '服务器错误', desc: `详细:<br>code ${error.message.substr(32)}<br>${method}<br>${args[0]}`, duration: 10 })
  } else if (/timeout of \d{1,5}ms exceeded/.test(error.message)) {
    Notice.error({ title: '请求超时', desc: `详细:<br>${method}<br>${args[0]}`, duration: 10 })
  } else if (error.message === 'Network Error') {
    Notice.error({ title: '网络错误', desc: `详细:<br>${method}<br>${args[0]}`, duration: 10 })
  } else {
    Notice.error({ title: '请求错误', desc: `详细:<br>error: ${error.message}<br>${method}<br>${args[0]}`, duration: 10 })
  }

  return _error
}
